Skip to content

Feature/pre registration#144

Closed
snu-BuMinSeong wants to merge 4 commits into
developfrom
feature/pre-registration
Closed

Feature/pre registration#144
snu-BuMinSeong wants to merge 4 commits into
developfrom
feature/pre-registration

Conversation

@snu-BuMinSeong

Copy link
Copy Markdown
Contributor

Summary

  • 사전등록 사용자 정보 수집 API를 추가했습니다.
  • 사전등록 사용자 조회 API를 추가했습니다.
  • 활성 사전등록은 DB 제약으로 하나만 유지되도록 보강했습니다.
  • 사전등록별 이메일 중복 등록을 방지했습니다.
  • 사전등록자 대상 일괄 이메일 발송 API를 추가했습니다.
  • 프로젝트 전반의 ruff, pyright 오류를 정리했습니다.

API

  • POST /api/v3/pre-registration/users

    • 활성 사전등록에 사용자 정보를 등록합니다.
  • GET /api/v3/pre-registration/users?active_only=true

    • 활성 사전등록 대상자만 조회합니다.
  • POST /api/v3/pre-registration/users/email

    • 사전등록자에게 이메일을 일괄 발송하고 성공/실패 결과를 반환합니다.

@snu-BuMinSeong snu-BuMinSeong requested a review from a team as a code owner July 5, 2026 13:26
@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@snu-BuMinSeong, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 19 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1a0bda43-63db-4c72-bfc0-cc3a6904dae2

📥 Commits

Reviewing files that changed from the base of the PR and between 556c2f3 and bdc8928.

📒 Files selected for processing (4)
  • wacruit/src/apps/pre_registration/schemas.py
  • wacruit/src/apps/pre_registration/services.py
  • wacruit/src/apps/pre_registration/views.py
  • wacruit/src/tests/pre_registration/test_pre_resgistration_service.py
📝 Walkthrough

Walkthrough

사전 등록(pre_registration) 도메인에 사용자 관리와 이메일 발송 기능이 추가되고, 관련 마이그레이션 및 테스트가 도입되었습니다. 아울러 다수 모듈에서 라우터 export 방식 통일, HTTP 상태코드 상수화, 미사용 import 제거, 예외 메시지/포맷 정리 등 광범위한 정리 작업이 수행되었습니다.

Changes

사전 등록 사용자 및 이메일 발송 기능

Layer / File(s) Summary
모델 스키마 및 제약 조건 확장
wacruit/src/apps/pre_registration/models.py, wacruit/src/database/migrations/versions/...add_pre_registration_active_key.py, ...add_pre_registration_user_table.py
PreRegistrationactive_key 컬럼, 유니크/체크 제약, validate_is_active 검증이 추가되고, PreRegistrationUser 모델과 관련 마이그레이션이 신설되었습니다.
예외 클래스 정리 및 신규 예외
wacruit/src/apps/pre_registration/exceptions.py
기존 예외 메시지가 수정되고 PreRegistUserAlreadyExistException(HTTP 409)이 추가되었습니다.
저장소 계층: 사용자 생성/조회
wacruit/src/apps/pre_registration/repositories.py
create_pre_registration_user, get_pre_registration_users 메서드가 추가되고 삭제 로직이 트랜잭션으로 감싸졌습니다.
요청/응답 스키마 추가
wacruit/src/apps/pre_registration/schemas.py
사용자 생성/응답 및 이메일 발송 요청/응답 Pydantic 모델 4개가 추가되었습니다.
서비스 계층: 이메일 발송 및 사용자 관리
wacruit/src/apps/pre_registration/services.py
EmailService 의존성 주입, IntegrityError 처리, 사용자 생성/조회, 이메일 발송 메서드가 추가되었습니다.
라우터 엔드포인트 추가
wacruit/src/apps/pre_registration/views.py
사용자 생성/조회, 이메일 발송용 엔드포인트와 검색 파라미터 클래스가 추가되었습니다.
테스트: FakeEmailService 및 서비스 테스트 확장
wacruit/src/tests/pre_registration/conftest.py, wacruit/src/tests/pre_registration/test_pre_resgistration_service.py
FakeEmailService가 추가되고 관련 서비스 테스트가 대폭 확장되었습니다.

Estimated code review effort: 3 (Moderate) | ~30 minutes

라우터 export 통일, import 정리 및 기타 리팩터링

Layer / File(s) Summary
라우터 export 방식 통일
wacruit/src/apps/*/__init__.py(announcement, dummy, faq, history, member, project, pre_registration, resume, review, seminar, sponsor, timeline, user, problem, recruiting)
각 앱의 router 노출이 alias import 대신 명시적 할당과 __all__로 통일되었습니다.
HTTP 상태코드 상수화
wacruit/src/apps/hodu/repositories.py, wacruit/src/apps/judge/repositories.py
하드코딩된 400 임계값이 HTTP_CLIENT_ERROR_STATUS_CODE 상수로 대체되었습니다.
Hodu 설정/스키마 정리
wacruit/src/apps/hodu/config.py, wacruit/src/apps/hodu/schemas.py
ConfigBaseSettings.Config를 상속하도록 변경되고, 상태 변환 로직이 딕셔너리 매핑으로 리팩터링되었습니다.
모델 컬럼/필터 조정
wacruit/src/apps/review/models.py, wacruit/src/apps/portfolio/file/repositories.py, wacruit/src/apps/project/models.py, wacruit/src/apps/member/models.py
Review.content 타입 확장, 불리언 필터 개선, 불필요 타입 참조 제거가 이루어졌습니다.
Resume 미리보기 길이 상수화
wacruit/src/apps/resume/models.py
하드코딩된 10PREVIEW_LENGTH 상수로 대체되었습니다.
User 저장소 메서드 제거 및 정리
wacruit/src/apps/user/repositories.py, wacruit/src/apps/user/dependencies.py, wacruit/src/apps/user/services.py
get_user_by_username 메서드가 삭제되고 관련 import/포맷이 정리되었습니다.
예외 포맷 정리
wacruit/src/apps/portfolio/*/exceptions.py, wacruit/src/apps/project/exceptions.py, wacruit/src/apps/timeline/exceptions.py, wacruit/src/apps/problem/exceptions.py
여러 예외 클래스의 super().__init__ 호출이 멀티라인 형식으로 통일되었습니다.
미사용 import 정리
다수 모듈 전반
미사용 import 제거 및 import 순서/구성 정리가 광범위하게 수행되었습니다.
테스트 정리 및 상수화
wacruit/src/tests/**
테스트 상수화, 미사용 import 제거, 환경변수 기본값 설정 등이 적용되었습니다.

Estimated code review effort: 2 (Simple) | ~15 minutes

Suggested reviewers: deveroskp

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive 제목이 'Feature/pre registration'로 너무 포괄적이고 이번 변경의 핵심인 사용자 수집·조회·대량 이메일 API를 드러내지 않습니다. 사전등록 사용자 조회/생성, 대량 이메일 발송, DB 제약 강화가 드러나는 구체적인 제목으로 바꾸세요.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed 설명은 사전등록 사용자 API 추가, 중복 방지, 대량 이메일 발송, ruff/pyright 정리에 모두 관련되어 있습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/pre-registration

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
wacruit/src/apps/portfolio/file/repositories.py (1)

28-32: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

불필요해진 pylint disable 주석 제거 필요.

# pylint: disable=singleton-comparisonis_uploaded == True 비교로 인한 경고를 억제하기 위한 것이었으나, 이제 불리언 컬럼을 직접 조건으로 사용하도록 변경되어 더 이상 해당 경고가 발생하지 않습니다. 남겨진 disable 주석은 향후 이 스코프 내 실제 위반을 가릴 수 있으므로 제거하는 것이 좋습니다.

♻️ 제안
     def get_portfolio_files(
         self, user_id: int, recruiting_id: int
     ) -> Sequence[PortfolioFile]:
-        # pylint: disable=singleton-comparison
         query = select(PortfolioFile).where(
             (PortfolioFile.user_id == user_id)
             & (PortfolioFile.recruiting_id == recruiting_id)
             & PortfolioFile.is_uploaded
         )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wacruit/src/apps/portfolio/file/repositories.py` around lines 28 - 32, Remove
the no-longer-needed pylint suppression from the repository query in
PortfolioFileRepository, since PortfolioFile.is_uploaded is now used directly
and no singleton-comparison warning is expected. Keep the
select(PortfolioFile).where(...) logic unchanged, and delete only the "# pylint:
disable=singleton-comparison" comment near the query construction.
wacruit/src/apps/pre_registration/schemas.py (1)

51-57: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

content/html_content에 길이 제한이 없습니다.

subjectmax_length=255가 있는데 content/html_content는 상한이 없습니다. 관리자 전용 엔드포인트라 위험은 낮지만, 다른 필드들과 일관되게 상한을 두면 외부 메일 제공자로 과도하게 큰 페이로드가 전달되는 것을 방지할 수 있습니다.

♻️ 제안
     subject: str = Field(..., min_length=1, max_length=255)
-    content: str = Field(..., min_length=1)
-    html_content: str | None = None
+    content: str = Field(..., min_length=1, max_length=10000)
+    html_content: str | None = Field(default=None, max_length=20000)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wacruit/src/apps/pre_registration/schemas.py` around lines 51 - 57,
`SendPreRegistrationEmailRequest`의 `content`와 `html_content`에 상한 길이가 없어 대용량
페이로드가 들어갈 수 있습니다. 이 스키마에서 `subject`처럼 `Field`에 적절한 `max_length`를 추가해 두 필드의 길이
제한을 맞추고, 관리자용 엔드포인트에서도 외부 메일 전송 전 입력 크기를 제어하도록 수정하세요.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@wacruit/src/apps/pre_registration/services.py`:
- Around line 150-181: The send_email_to_pre_registration_users flow is doing
bulk delivery synchronously in the request path, which can block the API and
exhaust workers as recipient counts grow. Update
SendPreRegistrationEmailResponse handling so
send_email_to_pre_registration_users in services.py hands off delivery work to
BackgroundTasks or a queue-based worker instead of looping over all users
inline, and add a recipient cap or batching in get_pre_registration_users usage
to prevent unbounded sends. Keep the existing email_service.send_email logic,
but move the execution out of the HTTP request lifecycle.

---

Nitpick comments:
In `@wacruit/src/apps/portfolio/file/repositories.py`:
- Around line 28-32: Remove the no-longer-needed pylint suppression from the
repository query in PortfolioFileRepository, since PortfolioFile.is_uploaded is
now used directly and no singleton-comparison warning is expected. Keep the
select(PortfolioFile).where(...) logic unchanged, and delete only the "# pylint:
disable=singleton-comparison" comment near the query construction.

In `@wacruit/src/apps/pre_registration/schemas.py`:
- Around line 51-57: `SendPreRegistrationEmailRequest`의 `content`와
`html_content`에 상한 길이가 없어 대용량 페이로드가 들어갈 수 있습니다. 이 스키마에서 `subject`처럼 `Field`에 적절한
`max_length`를 추가해 두 필드의 길이 제한을 맞추고, 관리자용 엔드포인트에서도 외부 메일 전송 전 입력 크기를 제어하도록 수정하세요.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 29ff490a-66e2-470b-9ab4-7372e1d7e9e9

📥 Commits

Reviewing files that changed from the base of the PR and between 7df14e5 and 556c2f3.

📒 Files selected for processing (97)
  • pyproject.toml
  • wacruit/src/apps/announcement/__init__.py
  • wacruit/src/apps/announcement/models.py
  • wacruit/src/apps/announcement/repositories.py
  • wacruit/src/apps/common/schemas.py
  • wacruit/src/apps/dummy/__init__.py
  • wacruit/src/apps/faq/__init__.py
  • wacruit/src/apps/faq/repositories.py
  • wacruit/src/apps/faq/views.py
  • wacruit/src/apps/history/__init__.py
  • wacruit/src/apps/history/repositories.py
  • wacruit/src/apps/history/services.py
  • wacruit/src/apps/hodu/config.py
  • wacruit/src/apps/hodu/repositories.py
  • wacruit/src/apps/hodu/schemas.py
  • wacruit/src/apps/judge/repositories.py
  • wacruit/src/apps/member/__init__.py
  • wacruit/src/apps/member/models.py
  • wacruit/src/apps/member/views.py
  • wacruit/src/apps/portfolio/file/aws/s3/client.py
  • wacruit/src/apps/portfolio/file/aws/s3/utils.py
  • wacruit/src/apps/portfolio/file/exceptions.py
  • wacruit/src/apps/portfolio/file/repositories.py
  • wacruit/src/apps/portfolio/file/services.py
  • wacruit/src/apps/portfolio/file/services_v2.py
  • wacruit/src/apps/portfolio/file/views_v2.py
  • wacruit/src/apps/portfolio/url/exceptions.py
  • wacruit/src/apps/portfolio/url/repositories.py
  • wacruit/src/apps/pre_registration/__init__.py
  • wacruit/src/apps/pre_registration/exceptions.py
  • wacruit/src/apps/pre_registration/models.py
  • wacruit/src/apps/pre_registration/repositories.py
  • wacruit/src/apps/pre_registration/schemas.py
  • wacruit/src/apps/pre_registration/services.py
  • wacruit/src/apps/pre_registration/views.py
  • wacruit/src/apps/problem/__init__.py
  • wacruit/src/apps/problem/exceptions.py
  • wacruit/src/apps/problem/models.py
  • wacruit/src/apps/problem/repositories.py
  • wacruit/src/apps/problem/repositories_v2.py
  • wacruit/src/apps/problem/schemas_v2.py
  • wacruit/src/apps/problem/services.py
  • wacruit/src/apps/problem/services_v2.py
  • wacruit/src/apps/problem/utils.py
  • wacruit/src/apps/problem/utils_v2.py
  • wacruit/src/apps/project/__init__.py
  • wacruit/src/apps/project/exceptions.py
  • wacruit/src/apps/project/models.py
  • wacruit/src/apps/project/repositories.py
  • wacruit/src/apps/project/services.py
  • wacruit/src/apps/recruiting/__init__.py
  • wacruit/src/apps/recruiting/models.py
  • wacruit/src/apps/recruiting/views.py
  • wacruit/src/apps/recruiting_info/models.py
  • wacruit/src/apps/resume/__init__.py
  • wacruit/src/apps/resume/models.py
  • wacruit/src/apps/resume/repositories.py
  • wacruit/src/apps/resume/schemas.py
  • wacruit/src/apps/resume/services.py
  • wacruit/src/apps/resume/views.py
  • wacruit/src/apps/review/__init__.py
  • wacruit/src/apps/review/models.py
  • wacruit/src/apps/review/repositories.py
  • wacruit/src/apps/seminar/__init__.py
  • wacruit/src/apps/seminar/repositories.py
  • wacruit/src/apps/seminar/schemas.py
  • wacruit/src/apps/seminar/views.py
  • wacruit/src/apps/sponsor/__init__.py
  • wacruit/src/apps/timeline/__init__.py
  • wacruit/src/apps/timeline/exceptions.py
  • wacruit/src/apps/timeline/repositories.py
  • wacruit/src/apps/timeline/services.py
  • wacruit/src/apps/user/__init__.py
  • wacruit/src/apps/user/dependencies.py
  • wacruit/src/apps/user/exceptions.py
  • wacruit/src/apps/user/repositories.py
  • wacruit/src/apps/user/services.py
  • wacruit/src/database/base.py
  • wacruit/src/database/connection.py
  • wacruit/src/database/migrations/versions/2026_06_28_1700-8c4d2f1a6b7e_add_pre_registration_active_key.py
  • wacruit/src/database/migrations/versions/2026_06_29_1000-4b0f9d2e7a61_add_pre_registration_user_table.py
  • wacruit/src/tests/announcement/conftest.py
  • wacruit/src/tests/announcement/test_announcement_service.py
  • wacruit/src/tests/announcement/test_announcement_views.py
  • wacruit/src/tests/conftest.py
  • wacruit/src/tests/faq/conftest.py
  • wacruit/src/tests/faq/test_faq_service.py
  • wacruit/src/tests/portfolio/file/conftest.py
  • wacruit/src/tests/portfolio/url/test_portfolio_url_service.py
  • wacruit/src/tests/pre_registration/conftest.py
  • wacruit/src/tests/pre_registration/test_pre_resgistration_service.py
  • wacruit/src/tests/resume/test_resume_service.py
  • wacruit/src/tests/seminar/test_seminar_service.py
  • wacruit/src/tests/timeline/conftest.py
  • wacruit/src/tests/user/conftest.py
  • wacruit/src/tests/user/test_user_service.py
  • wacruit/src/utils/mixins.py
💤 Files with no reviewable changes (23)
  • wacruit/src/apps/problem/utils.py
  • wacruit/src/apps/member/views.py
  • wacruit/src/apps/problem/utils_v2.py
  • wacruit/src/apps/member/models.py
  • wacruit/src/tests/seminar/test_seminar_service.py
  • wacruit/src/apps/portfolio/file/views_v2.py
  • wacruit/src/tests/user/conftest.py
  • wacruit/src/apps/review/models.py
  • wacruit/src/tests/resume/test_resume_service.py
  • wacruit/src/apps/timeline/services.py
  • wacruit/src/apps/seminar/schemas.py
  • wacruit/src/database/connection.py
  • wacruit/src/tests/faq/test_faq_service.py
  • wacruit/src/tests/timeline/conftest.py
  • wacruit/src/apps/user/services.py
  • wacruit/src/apps/resume/views.py
  • wacruit/src/tests/announcement/conftest.py
  • wacruit/src/apps/problem/schemas_v2.py
  • wacruit/src/apps/user/exceptions.py
  • wacruit/src/apps/resume/schemas.py
  • wacruit/src/apps/history/services.py
  • wacruit/src/apps/recruiting_info/models.py
  • pyproject.toml

Comment thread wacruit/src/apps/pre_registration/services.py Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant